package com.zkteco.biometric;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.TitledBorder;

public class ZKFPDemo extends JFrame{
	// 按钮组件
	JButton btnOpen = null;
	JButton btnEnroll = null;
	JButton btnVerify = null;
	JButton btnIdentify = null;
	JButton btnRegImg = null;
	JButton btnIdentImg = null;
	JButton btnClose = null;
	JLabel lblImg = null;
	
	// 状态标签
	JLabel lblStatus = null;
	JLabel lblDeviceInfo = null;
	JLabel lblFingerCount = null;
	
	// 文本区域
	private JTextArea textArea;
	private JScrollPane scrollPane;
	
	// 指纹图像尺寸
	int fpWidth = 0;
	int fpHeight = 0;
	
	// 验证用的模板
	private byte[] lastRegTemp = new byte[2048];
	private int cbRegTemp = 0;
	
	// 预注册模板数组
	private byte[][] regtemparray = new byte[3][2048];
	
	// 状态标志
	private boolean bRegister = false;
	private boolean bIdentify = true;
	private int iFid = 1;
	
	private int nFakeFunOn = 1;
	static final int enroll_cnt = 3;
	private int enroll_idx = 0;
	
	private byte[] imgbuf = null;
	private byte[] template = new byte[2048];
	private int[] templateLen = new int[1];
	
	private boolean mbStop = true;
	private long mhDevice = 0;
	private long mhDB = 0;
	private WorkThread workThread = null;
	
	// 颜色定义
	private final Color PRIMARY_COLOR = new Color(41, 128, 185);
	private final Color SUCCESS_COLOR = new Color(39, 174, 96);
	private final Color WARNING_COLOR = new Color(243, 156, 18);
	private final Color DANGER_COLOR = new Color(231, 76, 60);
	private final Color BACKGROUND_COLOR = new Color(236, 240, 241);
	private final Color PANEL_COLOR = Color.WHITE;
	
	public void launchFrame(){
		// 主窗口设置
		this.setLayout(new BorderLayout());
		this.setTitle("ZKFinger 指纹识别系统 v2.0");
		this.setSize(900, 750);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.getContentPane().setBackground(BACKGROUND_COLOR);
		
		// 创建主面板
		createMainPanel();
		
		// 设置窗口关闭事件
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent e) {
            	FreeSensor();
            }
		});
		
		this.setVisible(true);
	}
	
	private void createMainPanel() {
		// 顶部标题面板
		JPanel titlePanel = createTitlePanel();
		this.add(titlePanel, BorderLayout.NORTH);
		
		// 中心内容面板
		JPanel centerPanel = new JPanel(new BorderLayout());
		centerPanel.setBackground(BACKGROUND_COLOR);
		centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		
		// 左侧控制面板
		JPanel leftPanel = createControlPanel();
		centerPanel.add(leftPanel, BorderLayout.WEST);
		
		// 右侧指纹显示面板
		JPanel rightPanel = createImagePanel();
		centerPanel.add(rightPanel, BorderLayout.CENTER);
		
		this.add(centerPanel, BorderLayout.CENTER);
		
		// 底部状态和日志面板
		JPanel bottomPanel = createBottomPanel();
		this.add(bottomPanel, BorderLayout.SOUTH);
	}
	
	private JPanel createTitlePanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setBackground(PRIMARY_COLOR);
		panel.setPreferredSize(new Dimension(900, 60));
		panel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
		
		JLabel titleLabel = new JLabel("ZKFinger 指纹识别管理系统");
		titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
		titleLabel.setForeground(Color.WHITE);
		panel.add(titleLabel, BorderLayout.WEST);
		
		// 设备状态指示器
		lblStatus = new JLabel("● 设备未连接");
		lblStatus.setFont(new Font("微软雅黑", Font.BOLD, 14));
		lblStatus.setForeground(Color.WHITE);
		panel.add(lblStatus, BorderLayout.EAST);
		
		return panel;
	}
	
	private JPanel createControlPanel() {
		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		panel.setBackground(PANEL_COLOR);
		panel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createTitledBorder(
				BorderFactory.createLineBorder(PRIMARY_COLOR, 2),
				"设备控制",
				TitledBorder.LEFT,
				TitledBorder.TOP,
				new Font("微软雅黑", Font.BOLD, 14),
				PRIMARY_COLOR
			),
			BorderFactory.createEmptyBorder(10, 10, 10, 10)
		));
		panel.setPreferredSize(new Dimension(220, 600));
		
		// 设备管理区域
		JPanel devicePanel = new JPanel();
		devicePanel.setLayout(new BoxLayout(devicePanel, BoxLayout.Y_AXIS));
		devicePanel.setBackground(PANEL_COLOR);
		devicePanel.setBorder(BorderFactory.createTitledBorder("设备管理"));
		
		btnOpen = createStyledButton("连接设备", SUCCESS_COLOR);
		btnClose = createStyledButton("断开设备", DANGER_COLOR);
		
		devicePanel.add(btnOpen);
		devicePanel.add(Box.createVerticalStrut(10));
		devicePanel.add(btnClose);
		
		// 指纹操作区域
		JPanel fingerprintPanel = new JPanel();
		fingerprintPanel.setLayout(new BoxLayout(fingerprintPanel, BoxLayout.Y_AXIS));
		fingerprintPanel.setBackground(PANEL_COLOR);
		fingerprintPanel.setBorder(BorderFactory.createTitledBorder("指纹操作"));
		
		btnEnroll = createStyledButton("录入指纹", PRIMARY_COLOR);
		btnVerify = createStyledButton("验证指纹", WARNING_COLOR);
		btnIdentify = createStyledButton("识别指纹", new Color(155, 89, 182));
		
		fingerprintPanel.add(btnEnroll);
		fingerprintPanel.add(Box.createVerticalStrut(10));
		fingerprintPanel.add(btnVerify);
		fingerprintPanel.add(Box.createVerticalStrut(10));
		fingerprintPanel.add(btnIdentify);
		
		// 图像操作区域
		JPanel imagePanel = new JPanel();
		imagePanel.setLayout(new BoxLayout(imagePanel, BoxLayout.Y_AXIS));
		imagePanel.setBackground(PANEL_COLOR);
		imagePanel.setBorder(BorderFactory.createTitledBorder("图像处理"));
		
		btnRegImg = createStyledButton("图像录入", new Color(52, 152, 219));
		btnIdentImg = createStyledButton("图像验证", new Color(46, 204, 113));
		
		imagePanel.add(btnRegImg);
		imagePanel.add(Box.createVerticalStrut(10));
		imagePanel.add(btnIdentImg);
		
		// 设备信息区域
		JPanel infoPanel = new JPanel();
		infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
		infoPanel.setBackground(PANEL_COLOR);
		infoPanel.setBorder(BorderFactory.createTitledBorder("设备信息"));
		infoPanel.setMinimumSize(new Dimension(180, 70));
		infoPanel.setPreferredSize(new Dimension(180, 70));
		
		lblDeviceInfo = new JLabel("设备: 未连接");
		lblDeviceInfo.setFont(new Font("微软雅黑", Font.PLAIN, 11));
		lblFingerCount = new JLabel("指纹数量: 0");
		lblFingerCount.setFont(new Font("微软雅黑", Font.PLAIN, 11));
		
		infoPanel.add(Box.createVerticalStrut(5));
		infoPanel.add(lblDeviceInfo);
		infoPanel.add(Box.createVerticalStrut(3));
		infoPanel.add(lblFingerCount);
		infoPanel.add(Box.createVerticalStrut(5));
		
		// 添加所有面板，减少间距以适应更多内容
		panel.add(devicePanel);
		panel.add(Box.createVerticalStrut(5));
		panel.add(fingerprintPanel);
		panel.add(Box.createVerticalStrut(5));
		panel.add(imagePanel);
		panel.add(Box.createVerticalStrut(5));
		panel.add(infoPanel);
		panel.add(Box.createVerticalStrut(10));
		
		// 添加事件监听器
		addEventListeners();
		
		return panel;
	}
	
	private JButton createStyledButton(String text, Color color) {
		JButton button = new JButton(text);
		button.setFont(new Font("微软雅黑", Font.BOLD, 12));
		button.setBackground(color);
		button.setForeground(Color.WHITE);
		button.setBorder(BorderFactory.createEmptyBorder(8, 12, 8, 12));
		button.setFocusPainted(false);
		button.setCursor(new Cursor(Cursor.HAND_CURSOR));
		button.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
		button.setPreferredSize(new Dimension(180, 35));
		
		// 添加悬停效果
		button.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseEntered(java.awt.event.MouseEvent evt) {
				button.setBackground(color.darker());
			}
			public void mouseExited(java.awt.event.MouseEvent evt) {
				button.setBackground(color);
			}
		});
		
		return button;
	}
	
	private JPanel createImagePanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setBackground(PANEL_COLOR);
		panel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createTitledBorder(
				BorderFactory.createLineBorder(PRIMARY_COLOR, 2),
				"指纹图像显示",
				TitledBorder.CENTER,
				TitledBorder.TOP,
				new Font("微软雅黑", Font.BOLD, 14),
				PRIMARY_COLOR
			),
			BorderFactory.createEmptyBorder(15, 15, 15, 15)
		));
		
		// 创建指纹图像显示区域
		lblImg = new JLabel();
		lblImg.setHorizontalAlignment(JLabel.CENTER);
		lblImg.setVerticalAlignment(JLabel.CENTER);
		lblImg.setPreferredSize(new Dimension(320, 320));
		lblImg.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createLineBorder(Color.GRAY, 2),
			BorderFactory.createEmptyBorder(10, 10, 10, 10)
		));
		lblImg.setBackground(Color.WHITE);
		lblImg.setOpaque(true);
		
		// 默认显示文本
		lblImg.setText("<html><div style='text-align: center;'>" +
					  "<p style='font-size: 18px; color: #7f8c8d;'>指纹图像</p>" +
					  "<p style='font-size: 14px; color: #95a5a6;'>等待指纹图像...</p>" +
					  "</div></html>");
		
		panel.add(lblImg, BorderLayout.CENTER);
		
		return panel;
	}
	
	private JPanel createBottomPanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setBackground(BACKGROUND_COLOR);
		panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		
		// 创建日志面板
		JPanel logPanel = new JPanel(new BorderLayout());
		logPanel.setBackground(PANEL_COLOR);
		logPanel.setBorder(BorderFactory.createTitledBorder(
			BorderFactory.createLineBorder(PRIMARY_COLOR, 1),
			"系统日志",
			TitledBorder.LEFT,
			TitledBorder.TOP,
			new Font("微软雅黑", Font.BOLD, 12),
			PRIMARY_COLOR
		));
		
		textArea = new JTextArea(6, 50);
		// 使用支持中文的字体，优先使用微软雅黑，如果没有则使用系统默认字体
		Font logFont;
		try {
			logFont = new Font("微软雅黑", Font.PLAIN, 12);
			// 测试字体是否支持中文
			if (!logFont.canDisplay('中')) {
				logFont = new Font("宋体", Font.PLAIN, 12);
			}
			if (!logFont.canDisplay('中')) {
				logFont = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
			}
		} catch (Exception e) {
			logFont = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
		}
		textArea.setFont(logFont);
		textArea.setBackground(new Color(248, 249, 250));
		textArea.setForeground(new Color(52, 73, 94));
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);
		textArea.setText("系统启动完成，请连接指纹识别设备...\n");
		
		scrollPane = new JScrollPane(textArea);
		scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		
		logPanel.add(scrollPane, BorderLayout.CENTER);
		panel.add(logPanel, BorderLayout.CENTER);
		
		return panel;
	}
	
	private void addEventListeners() {
		btnOpen.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (0 != mhDevice) {
					appendLog("[警告] 设备已连接，请先断开当前设备！");
					return;
				}
				
				int ret = FingerprintSensorErrorCode.ZKFP_ERR_OK;
				cbRegTemp = 0;
				bRegister = false;
				bIdentify = false;
				iFid = 1;
				enroll_idx = 0;
				
				appendLog("[信息] 正在初始化指纹识别SDK...");
				
				if (FingerprintSensorErrorCode.ZKFP_ERR_OK != FingerprintSensorEx.Init()) {
					appendLog("[错误] SDK初始化失败！");
					return;
				}
				
				ret = FingerprintSensorEx.GetDeviceCount();
				if (ret < 0) {
					appendLog("[错误] 未检测到指纹识别设备！请检查设备连接。");
					FreeSensor();
					return;
				}
				
				appendLog("[信息] 检测到 " + ret + " 个指纹识别设备");
				
				if (0 == (mhDevice = FingerprintSensorEx.OpenDevice(0))) {
					appendLog("[错误] 打开设备失败，错误代码: " + ret);
					FreeSensor();
					return;
				}
				
				if (0 == (mhDB = FingerprintSensorEx.DBInit())) {
					appendLog("[错误] 数据库初始化失败，错误代码: " + ret);
					FreeSensor();
					return;
				}
				
				// 获取设备参数
				byte[] paramValue = new byte[4];
				int[] size = new int[1];
				
				size[0] = 4;
				FingerprintSensorEx.GetParameters(mhDevice, 1, paramValue, size);
				fpWidth = byteArrayToInt(paramValue);
				size[0] = 4;
				FingerprintSensorEx.GetParameters(mhDevice, 2, paramValue, size);
				fpHeight = byteArrayToInt(paramValue);
				
				imgbuf = new byte[fpWidth * fpHeight];
				
				// 更新UI状态
				lblStatus.setText("● 设备已连接");
				lblStatus.setForeground(Color.WHITE);
				lblDeviceInfo.setText("设备: ZKFinger (" + fpWidth + "x" + fpHeight + ")");
				lblFingerCount.setText("指纹数量: 0");
				
				mbStop = false;
				workThread = new WorkThread();
				workThread.start();
				
				appendLog("[成功] 设备连接成功！图像尺寸: " + fpWidth + "x" + fpHeight);
			}
		});
		
		btnClose.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				FreeSensor();
				lblStatus.setText("● 设备未连接");
				lblDeviceInfo.setText("设备: 未连接");
				lblFingerCount.setText("指纹数量: 0");
				lblImg.setIcon(null);
				lblImg.setText("<html><div style='text-align: center;'>" +
							  "<p style='font-size: 18px; color: #7f8c8d;'>指纹图像</p>" +
							  "<p style='font-size: 14px; color: #95a5a6;'>等待指纹图像...</p>" +
							  "</div></html>");
				appendLog("[信息] 设备已断开连接");
			}
		});
		
		btnEnroll.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(0 == mhDevice) {
					appendLog("[警告] 请先连接指纹识别设备！");
					return;
				}
				if(!bRegister) {
					enroll_idx = 0;
					bRegister = true;
					appendLog("[信息] 开始录入指纹，请按压手指3次...");
				}
			}
			});
		
		btnVerify.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(0 == mhDevice) {
					appendLog("[警告] 请先连接指纹识别设备！");
					return;
				}
				if(bRegister) {
					enroll_idx = 0;
					bRegister = false;
				}
				if(bIdentify) {
					bIdentify = false;
				}
				appendLog("[信息] 切换到验证模式 (1:1比对)");
			}
			});
		
		btnIdentify.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(0 == mhDevice) {
					appendLog("[警告] 请先连接指纹识别设备！");
					return;
				}
				if(bRegister) {
					enroll_idx = 0;
					bRegister = false;
				}
				if(!bIdentify) {
					bIdentify = true;
				}
				appendLog("[信息] 切换到识别模式 (1:N搜索)");
			}
			});
		
		btnRegImg.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(0 == mhDB) {
					appendLog("[警告] 请先连接指纹识别设备！");
					return;
				}
				
				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("BMP图像文件", "bmp"));
				fileChooser.setDialogTitle("选择指纹图像文件");
				
				if (fileChooser.showOpenDialog(ZKFPDemo.this) == JFileChooser.APPROVE_OPTION) {
					String path = fileChooser.getSelectedFile().getAbsolutePath();
					appendLog("[信息] 正在从图像文件录入指纹: " + path);
					
				byte[] fpTemplate = new byte[2048];
				int[] sizeFPTemp = new int[1];
				sizeFPTemp[0] = 2048;
					int ret = FingerprintSensorEx.ExtractFromImage(mhDB, path, 500, fpTemplate, sizeFPTemp);
					
					if (0 == ret) {
						ret = FingerprintSensorEx.DBAdd(mhDB, iFid, fpTemplate);
						if (0 == ret) {
						iFid++;
                    	cbRegTemp = sizeFPTemp[0];
                        System.arraycopy(fpTemplate, 0, lastRegTemp, 0, cbRegTemp);
							lblFingerCount.setText("指纹数量: " + (iFid - 1));
							appendLog("[成功] 图像指纹录入成功！指纹ID: " + (iFid - 1));
						} else {
							appendLog("[错误] 数据库添加失败，错误代码: " + ret);
						}
					} else {
						appendLog("[错误] 图像特征提取失败，错误代码: " + ret);
					}
				}
			}
		});
		
		btnIdentImg.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(0 == mhDB) {
					appendLog("[警告] 请先连接指纹识别设备！");
					return;
				}
				
				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("BMP图像文件", "bmp"));
				fileChooser.setDialogTitle("选择要验证的指纹图像文件");
				
				if (fileChooser.showOpenDialog(ZKFPDemo.this) == JFileChooser.APPROVE_OPTION) {
					String path = fileChooser.getSelectedFile().getAbsolutePath();
					appendLog("[信息] 正在验证图像文件: " + path);
					
				byte[] fpTemplate = new byte[2048];
				int[] sizeFPTemp = new int[1];
				sizeFPTemp[0] = 2048;
				int ret = FingerprintSensorEx.ExtractFromImage(mhDB, path, 500, fpTemplate, sizeFPTemp);
					
					if (0 == ret) {
						if (bIdentify) {
						int[] fid = new int[1];
							int[] score = new int[1];
						ret = FingerprintSensorEx.DBIdentify(mhDB, fpTemplate, fid, score);
							if (ret == 0) {
								appendLog("[成功] 识别成功！指纹ID: " + fid[0] + "，匹配分数: " + score[0]);
							} else {
								appendLog("[错误] 识别失败，未找到匹配的指纹");
							}
						} else {
							if(cbRegTemp <= 0) {
								appendLog("[警告] 请先录入指纹模板！");
							} else {
								ret = FingerprintSensorEx.DBMatch(mhDB, lastRegTemp, fpTemplate);
								if(ret > 0) {
									appendLog("[成功] 验证成功！匹配分数: " + ret);
								} else {
									appendLog("[错误] 验证失败，指纹不匹配");
								}
							}
						}
					} else {
						appendLog("[错误] 图像特征提取失败，错误代码: " + ret);
					}
				}
			}
		});
	}
	
	private void appendLog(String message) {
		SwingUtilities.invokeLater(() -> {
			String timestamp = java.time.LocalTime.now().format(
				java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss")
			);
			textArea.append("[" + timestamp + "] " + message + "\n");
			textArea.setCaretPosition(textArea.getDocument().getLength());
		});
	}
	
	private void FreeSensor() {
		mbStop = true;
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (0 != mhDB) {
			FingerprintSensorEx.DBFree(mhDB);
			mhDB = 0;
		}
		if (0 != mhDevice) {
			FingerprintSensorEx.CloseDevice(mhDevice);
			mhDevice = 0;
		}
		FingerprintSensorEx.Terminate();
	}
	
	public static void writeBitmap(byte[] imageBuf, int nWidth, int nHeight, String path) throws IOException {
		java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
		java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);

		int w = (((nWidth+3)/4)*4);
		int bfType = 0x424d;
		int bfSize = 54 + 1024 + w * nHeight;
		int bfReserved1 = 0;
		int bfReserved2 = 0;
		int bfOffBits = 54 + 1024;

		dos.writeShort(bfType);
		dos.write(changeByte(bfSize), 0, 4);
		dos.write(changeByte(bfReserved1), 0, 2);
		dos.write(changeByte(bfReserved2), 0, 2);
		dos.write(changeByte(bfOffBits), 0, 4);

		int biSize = 40;
		int biWidth = nWidth;
		int biHeight = nHeight;
		int biPlanes = 1;
		int biBitcount = 8;
		int biCompression = 0;
		int biSizeImage = w * nHeight;
		int biXPelsPerMeter = 0;
		int biYPelsPerMeter = 0;
		int biClrUsed = 0;
		int biClrImportant = 0;

		dos.write(changeByte(biSize), 0, 4);
		dos.write(changeByte(biWidth), 0, 4);
		dos.write(changeByte(biHeight), 0, 4);
		dos.write(changeByte(biPlanes), 0, 2);
		dos.write(changeByte(biBitcount), 0, 2);
		dos.write(changeByte(biCompression), 0, 4);
		dos.write(changeByte(biSizeImage), 0, 4);
		dos.write(changeByte(biXPelsPerMeter), 0, 4);
		dos.write(changeByte(biYPelsPerMeter), 0, 4);
		dos.write(changeByte(biClrUsed), 0, 4);
		dos.write(changeByte(biClrImportant), 0, 4);

		for (int i = 0; i < 256; i++) {
			dos.writeByte(i);
			dos.writeByte(i);
			dos.writeByte(i);
			dos.writeByte(0);
		}

		byte[] filter = null;
		if (w > nWidth) {
			filter = new byte[w-nWidth];
		}
		
		for(int i=0;i<nHeight;i++) {
			dos.write(imageBuf, (nHeight-1-i)*nWidth, nWidth);
			if (w > nWidth)
				dos.write(filter, 0, w-nWidth);
		}
		dos.flush();
		dos.close();
		fos.close();
	}

	public static byte[] changeByte(int data) {
		return intToByteArray(data);
	}
	
	public static byte[] intToByteArray(final int number) {
		byte[] abyte = new byte[4];  
	    abyte[0] = (byte) (0xff & number);  
	    abyte[1] = (byte) ((0xff00 & number) >> 8);  
	    abyte[2] = (byte) ((0xff0000 & number) >> 16);  
	    abyte[3] = (byte) ((0xff000000 & number) >> 24);  
	    return abyte; 
	}	 
		 
		public static int byteArrayToInt(byte[] bytes) {
			int number = bytes[0] & 0xFF;  
		    number |= ((bytes[1] << 8) & 0xFF00);  
		    number |= ((bytes[2] << 16) & 0xFF0000);  
		    number |= ((bytes[3] << 24) & 0xFF000000);  
		    return number;  
		 }
	
		private class WorkThread extends Thread {
	        @Override
	        public void run() {
	            super.run();
	            int ret = 0;
	            while (!mbStop) {
	            	templateLen[0] = 2048;
            	if (0 == (ret = FingerprintSensorEx.AcquireFingerprint(mhDevice, imgbuf, template, templateLen))) {
            		if (nFakeFunOn == 1) {
                    		byte[] paramValue = new byte[4];
            				int[] size = new int[1];
            				size[0] = 4;
            				int nFakeStatus = 0;
            				ret = FingerprintSensorEx.GetParameters(mhDevice, 2004, paramValue, size);
            				nFakeStatus = byteArrayToInt(paramValue);
            				System.out.println("ret = "+ ret +",nFakeStatus=" + nFakeStatus);
        				if (0 == ret && (byte)(nFakeStatus & 31) != 31) {
        					appendLog("[警告] 检测到可疑指纹，可能是假指纹！");
        					continue;
        				}
                	}
                	OnCaptureOK(imgbuf);
                    	OnExtractOK(template, templateLen[0]);
                    	String strBase64 = FingerprintSensorEx.BlobToBase64(template, templateLen[0]);
                	System.out.println("Base64模板: " + strBase64);
	            	}
	                try {
	                    Thread.sleep(500);
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
            }
        }
    }
	
	private void OnCaptureOK(byte[] imgBuf) {
			try {
				writeBitmap(imgBuf, fpWidth, fpHeight, "fingerprint.bmp");
			ImageIcon icon = new ImageIcon(ImageIO.read(new File("fingerprint.bmp")));
			// 缩放图像以适应显示区域
			Image img = icon.getImage().getScaledInstance(300, 300, Image.SCALE_SMOOTH);
			lblImg.setIcon(new ImageIcon(img));
			lblImg.setText("");
			} catch (IOException e) {
				e.printStackTrace();
			appendLog("[错误] 指纹图像保存失败: " + e.getMessage());
		}
	}
	
	private void OnExtractOK(byte[] template, int len) {
		if(bRegister) {
				int[] fid = new int[1];
			int[] score = new int[1];
                int ret = FingerprintSensorEx.DBIdentify(mhDB, template, fid, score);
            if (ret == 0) {
                appendLog("[警告] 该指纹已被录入，指纹ID: " + fid[0] + "，取消录入");
                    bRegister = false;
                    enroll_idx = 0;
                    return;
                }
            if (enroll_idx > 0 && FingerprintSensorEx.DBMatch(mhDB, regtemparray[enroll_idx-1], template) <= 0) {
            	appendLog("[警告] 请按压同一根手指进行录入");
                    return;
                }
                System.arraycopy(template, 0, regtemparray[enroll_idx], 0, 2048);
                enroll_idx++;
                if (enroll_idx == 3) {
                	int[] _retLen = new int[1];
                    _retLen[0] = 2048;
                    byte[] regTemp = new byte[_retLen[0]];
                    
                    if (0 == (ret = FingerprintSensorEx.DBMerge(mhDB, regtemparray[0], regtemparray[1], regtemparray[2], regTemp, _retLen)) &&
                    		0 == (ret = FingerprintSensorEx.DBAdd(mhDB, iFid, regTemp))) {
                    	iFid++;
                    	cbRegTemp = _retLen[0];
                        System.arraycopy(regTemp, 0, lastRegTemp, 0, cbRegTemp);
                        String strBase64 = FingerprintSensorEx.BlobToBase64(regTemp, cbRegTemp);
                    lblFingerCount.setText("指纹数量: " + (iFid - 1));
                    appendLog("[成功] 指纹录入成功！指纹ID: " + (iFid - 1));
                    } else {
                	appendLog("[错误] 指纹录入失败，错误代码: " + ret);
                    }
                    bRegister = false;
            } else {
            	appendLog("[信息] 请继续按压手指，还需要 " + (3 - enroll_idx) + " 次");
            }
		} else {
			if (bIdentify) {
				int[] fid = new int[1];
				int[] score = new int[1];
				int ret = FingerprintSensorEx.DBIdentify(mhDB, template, fid, score);
                if (ret == 0) {
                	appendLog("[成功] 识别成功！指纹ID: " + fid[0] + "，匹配分数: " + score[0]);
                } else {
                	appendLog("[错误] 识别失败，未找到匹配的指纹");
                }
			} else {
				if(cbRegTemp <= 0) {
					appendLog("[警告] 请先录入指纹模板！");
				} else {
						int ret = FingerprintSensorEx.DBMatch(mhDB, lastRegTemp, template);
					if(ret > 0) {
						appendLog("[成功] 验证成功！匹配分数: " + ret);
					} else {
						appendLog("[错误] 验证失败，指纹不匹配");
					}
					}
				}
			}
		}
		
		public static void main(String[] args) {
		// 设置控制台编码为UTF-8，解决中文乱码问题
		try {
			System.setProperty("file.encoding", "UTF-8");
			System.setProperty("console.encoding", "UTF-8");
			// 对于Windows系统，设置输出流编码
			if (System.getProperty("os.name").toLowerCase().contains("windows")) {
				System.setOut(new java.io.PrintStream(System.out, true, "UTF-8"));
				System.setErr(new java.io.PrintStream(System.err, true, "UTF-8"));
			}
		} catch (Exception e) {
			// 如果设置编码失败，继续运行
		}
		
		SwingUtilities.invokeLater(() -> {
			new ZKFPDemo().launchFrame();
		});
		}
}